#include "wds_enemy_collection.h"
#include "wds_enemy.h"
#include "wds_pickup.h"
#include "wds_bullet.h"

#include "num/rand.h"
#include "util/mmgr.h"		    // Needs to come in early
#include "util/common_macros.h"		// macros
#include "util/log.h"		    // logging
#include "util/timer.h"		    // logging

WDSEnemyCollection::WDSEnemyCollection(WDSEnemy::ENEMY_TYPES Type,
									   unsigned long NameCRC
									   )  : m_Type(Type),
											m_NameCRC(NameCRC)
{
	
}


WDSEnemyCollection::~WDSEnemyCollection()
{
	Clear();
}

void		WDSEnemyCollection::RenderDecal(const math::Vec2& Offset,float Scale)
{
	//render dead 
	for(unsigned int i = 0; i < m_Enemies.size(); i++)
	{
		WDSEnemy*  pEnemy = m_Enemies[i];
		if(pEnemy->GetEnemeyState() == WDSEnemy::ENEMY_STATES_DEAD )
			pEnemy->Render(Offset, Scale);
		//pEnemy->RenderSFX(Offset, Scale);
			
	}
}

void		WDSEnemyCollection::RenderDead(const math::Vec2& Offset,float Scale)
{
	// crawl first 
	for(unsigned int i = 0; i < m_Enemies.size(); i++)
	{
		WDSEnemy*  pEnemy = m_Enemies[i];
		if(pEnemy->IsAlive() || pEnemy->GetIsCrawl())
			pEnemy->Render(Offset, Scale);
		//pEnemy->RenderSFX(Offset, Scale);
			
	}

	// dying enemies
	for(unsigned int i = 0; i < m_Enemies.size(); i++)
	{
		WDSEnemy*  pEnemy = m_Enemies[i];
		if(!pEnemy->IsAlive() && pEnemy->GetEnemeyState() != WDSEnemy::ENEMY_STATES_DEAD)
			pEnemy->Render(Offset, Scale);
		//pEnemy->RenderSFX(Offset, Scale);
			
	}
}


void		WDSEnemyCollection::Render(const math::Vec2& Offset,float Scale)
{

	// render alive later
	for(unsigned int i = 0; i < m_Enemies.size(); i++)
	{
		WDSEnemy*  pEnemy = m_Enemies[i];
		if(pEnemy->IsAlive() && !pEnemy->GetIsCrawl())
			pEnemy->Render(Offset, Scale);
		//pEnemy->RenderSFX(Offset, Scale);
			
	}
	
}

void	WDSEnemyCollection::RenderShadow(const math::Vec2& Offset, float Scale)
{
	for(unsigned int i = 0; i < m_Enemies.size(); i++)
	{
		WDSEnemy*  pEnemy = m_Enemies[i];
		pEnemy->RenderShadow(Offset, Scale);
	}

}
	
void		WDSEnemyCollection::Tick(float dt, float GameDifficulty, float PlayerReflex, const math::Vec2& Offset)
{
	for(unsigned int i = 0; i < m_Enemies.size(); i++)
	{
		WDSEnemy*  pEnemy = m_Enemies[i];
		pEnemy->Tick(dt, GameDifficulty, PlayerReflex, Offset);
	}
}



void		WDSEnemyCollection::Clear()
{
	int C = (int)m_Enemies.size();
	for( int i = C - 1; i >= 0; i--)
	{
		WDSEnemy*  pEnemyCraft = m_Enemies[i];
		//pEnemyCraft->Clear();
		UTIL_SAFE_DELETE(pEnemyCraft);
	}
	m_Enemies.resize(0);
}
	

void		WDSEnemyCollection::Spawn(WDSEnemy::ENEMY_TYPES EnemyType, 
									  WDSEnemy::ENEMY_SPAWN_TYPE SpawnType, 
									  const math::Vec2& Offset
									  )
{
	
	const float MAX_ENEMY_COUNT = 100;
	if((int)m_Enemies.size() >= MAX_ENEMY_COUNT)
		return;

	bool	bSpawn =false;	
	

	int SpawnPickupIndex = 0;

	/*
	WDSPickup::PICKUP_TYPES	TempPickup = WDSPickup::PICKUP_TYPE_NONE;
	if(pEnemyInfo->Count > 0 && pEnemyInfo->SpawnTypeEnumInt > 0)
	{
		// only one obj will spawn that pickup
		SpawnPickupIndex = num::RAND32::Instance().RandInt(0,pEnemyInfo->Count-1);
		
	}
	*/

	
	WDSEnemy* pEnemy = NULL;
	
	bSpawn =false;
	for( int i = 0; i < (int)m_Enemies.size(); i++)
	{
		pEnemy = m_Enemies[i];
		if(pEnemy->IsReadyToSpawn())
		{
			
			bSpawn = true;
			i = (int)m_Enemies.size();
		}
	}

	if(!bSpawn)
	{
		
		pEnemy = CreateEnemy(EnemyType);
		if(pEnemy)
		{
			m_Enemies.push_back(pEnemy);
			//if(pEnemyInfo->Name.size() > 0)
			//	pEnemyCraft->Load(pEnemyInfo->Name);
			
		}
	}

	if(pEnemy)
	{
		
		pEnemy->InitSpawning(
									0, //pEnemyInfo->DelaySpawn ,									
									WDSPickup::PICKUP_TYPE_NONE,
									SpawnType,
									Offset
									);		
		

		pEnemy->ReSpawn();
	}
	
}

WDSEnemy*		WDSEnemyCollection::GetEnemyByIndex(int Index)
{
	return m_Enemies[Index];
}

bool			WDSEnemyCollection::HitTest(WDSBullet* pBullet)
{
	bool ReturnV = false;
	for(unsigned int i = 0; i < m_Enemies.size(); i++)
	{
		WDSEnemy*  pEnemy = m_Enemies[i];
		if( pEnemy->HitTest(pBullet))
		{
			if(pBullet && pBullet->GetIsTypeGauss())			
				ReturnV = true; 
			else
				return true;
		}
	}
	
	return ReturnV;
}


WDSEnemy*			WDSEnemyCollection::CreateEnemy(WDSEnemy::ENEMY_TYPES EnemyType)
{
	switch(EnemyType)
	{
	case WDSEnemy::ENEMY_TYPES_NORMAL:
		return new WDSEnemy(EnemyType);
		break;
	}
	return NULL;
}


